|___* demos/gtk-demo/demo.ui: |___* gtk/gtk-builder-convert: |___*
authorJohan Dahlin <jdahlin@lozenge>
Mon, 9 Jul 2007 13:40:10 +0000 (13:40 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Mon, 9 Jul 2007 13:40:10 +0000 (13:40 +0000)
2007-07-09  Johan Dahlin,,,  <jdahlin@lozenge>

|___* demos/gtk-demo/demo.ui:
|___* gtk/gtk-builder-convert:
|___* gtk/gtkactiongroup.c: (gtk_action_group_buildable_init),
|___(gtk_action_group_buildable_add_child),
|___(accelerator_start_element),
|___(gtk_action_group_buildable_custom_tag_start),
|___(gtk_action_group_buildable_custom_tag_end):
|___* gtk/gtkuimanager.c: (child_hierarchy_changed_cb),
|___(gtk_ui_manager_buildable_construct_child):
|___* tests/buildertest.c: (test_uimanager_simple):

|___Add actiongroup/action accelerator support for builder. #454654

svn path=/trunk/; revision=18408

ChangeLog
demos/gtk-demo/demo.ui
gtk/gtk-builder-convert
gtk/gtkactiongroup.c
gtk/gtkuimanager.c
tests/buildertest.c

index cc66a6bb8b19fffb3057caef874d33fb61760221..d98a416d6fbf39ec22b7a3b76b3fbae2388e9eb1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2007-07-09  Johan Dahlin,,,  <jdahlin@lozenge>
+
+       * demos/gtk-demo/demo.ui:
+       * gtk/gtk-builder-convert:
+       * gtk/gtkactiongroup.c: (gtk_action_group_buildable_init),
+       (gtk_action_group_buildable_add_child),
+       (accelerator_start_element),
+       (gtk_action_group_buildable_custom_tag_start),
+       (gtk_action_group_buildable_custom_tag_end):
+       * gtk/gtkuimanager.c: (child_hierarchy_changed_cb),
+       (gtk_ui_manager_buildable_construct_child):
+       * tests/buildertest.c: (test_uimanager_simple):
+
+       Add actiongroup/action accelerator support for builder. #454654
+
 2007-07-08  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkbuilderparser.c (pgettext): Support old-style
index 26d668997e94a857bec6c06d345d51123b72a632..1c84db2b581da5aa6e4d4cb2efb2bc9dc4f85e60 100644 (file)
                         <property name="stock_id">gtk-about</property>
                         <signal handler="about_activate" name="activate"/>
                     </object>
+                    <accelerator key="F1"/>
                 </child>
             </object>
         </child>
index d77f8c3d16e4b2621a299bca6e2194f3bc193410..59218d555f3eaf03bedd6a441fc2b1d0614354c1 100755 (executable)
@@ -92,6 +92,16 @@ def get_signal_nodes(node):
             signals.append(child)
     return signals
 
+def get_accelerator_nodes(node):
+    assert node.tagName == 'object'
+    accelerators = []
+    for child in node.childNodes:
+        if child.nodeType == Node.TEXT_NODE:
+            continue
+        if child.tagName == 'accelerator':
+            accelerators.append(child)
+    return accelerators
+
 def get_object_node(child_node):
     assert child_node.tagName == 'child'
     nodes = []
@@ -418,6 +428,15 @@ class GtkBuilderConverter(object):
         group.appendChild(child)
         child.appendChild(action)
 
+        for accelerator in get_accelerator_nodes(node):
+            signal = accelerator.getAttribute('signal')
+            if signal_name != 'activate':
+                print 'Unhandled accelerator signal for %s::%s' % (
+                    node.getAttribute('class'), signal_name)
+                continue
+            accelerator.removeAttribute('signal')
+            child.appendChild(accelerator)
+
     def _convert_sizegroup(self, node, prop):
         # This is Gazpacho only
         node.removeChild(prop)
index 34ca057bb3afec1be216f57abf30a2525a3c33af..b9d6ee0837c41cb171a290e9dd687be1acd02a1d 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <config.h>
+#include <string.h>
 
 #include "gtkactiongroup.h"
 #include "gtkbuildable.h"
@@ -39,6 +40,7 @@
 #include "gtkradioaction.h"
 #include "gtkaccelmap.h"
 #include "gtkmarshalers.h"
+#include "gtkbuilderprivate.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
@@ -97,6 +99,17 @@ static void gtk_action_group_buildable_add_child (GtkBuildable  *buildable,
 static void gtk_action_group_buildable_set_name (GtkBuildable *buildable,
                                                 const gchar  *name);
 static const gchar* gtk_action_group_buildable_get_name (GtkBuildable *buildable);
+static gboolean gtk_action_group_buildable_custom_tag_start (GtkBuildable     *buildable,
+                                                            GtkBuilder       *builder,
+                                                            GObject          *child,
+                                                            const gchar      *tagname,
+                                                            GMarkupParser    *parser,
+                                                            gpointer         *data);
+static void gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
+                                                      GtkBuilder   *builder,
+                                                      GObject      *child,
+                                                      const gchar  *tagname,
+                                                      gpointer     *user_data);
 
 GType
 gtk_action_group_get_type (void)
@@ -298,6 +311,8 @@ gtk_action_group_buildable_init (GtkBuildableIface *iface)
   iface->add_child = gtk_action_group_buildable_add_child;
   iface->set_name = gtk_action_group_buildable_set_name;
   iface->get_name = gtk_action_group_buildable_get_name;
+  iface->custom_tag_start = gtk_action_group_buildable_custom_tag_start;
+  iface->custom_tag_end = gtk_action_group_buildable_custom_tag_end;
 }
 
 static void
@@ -306,8 +321,8 @@ gtk_action_group_buildable_add_child (GtkBuildable  *buildable,
                                      GObject       *child,
                                      const gchar   *type)
 {
-  gtk_action_group_add_action (GTK_ACTION_GROUP (buildable),
-                              GTK_ACTION (child));
+  gtk_action_group_add_action_with_accel (GTK_ACTION_GROUP (buildable),
+                                         GTK_ACTION (child), NULL);
 }
 
 static void
@@ -325,6 +340,113 @@ gtk_action_group_buildable_get_name (GtkBuildable *buildable)
   return self->private_data->name;
 }
 
+typedef struct {
+  GObject *child;
+  guint    key;
+  guint    modifiers;
+} AcceleratorParserData;
+
+static void
+accelerator_start_element (GMarkupParseContext *context,
+                          const gchar         *element_name,
+                          const gchar        **names,
+                          const gchar        **values,
+                          gpointer             user_data,
+                          GError             **error)
+{
+  gint i;
+  guint key = 0;
+  gint modifiers = 0;
+  AcceleratorParserData *parser_data = (AcceleratorParserData*)user_data;
+
+  if (strcmp (element_name, "accelerator") != 0)
+    g_warning ("Unknown <accelerator> tag: %s", element_name);
+
+  for (i = 0; names[i]; i++)
+    {
+      if (strcmp (names[i], "key") == 0)
+       key = gdk_keyval_from_name (values[i]);
+      else if (strcmp (names[i], "modifiers") == 0)
+       {
+         if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE,
+                                              values[i],
+                                              &modifiers,
+                                              error))
+             return;
+       }
+    }
+
+  if (key == 0)
+    {
+      g_warning ("<accelerator> requires a key attribute");
+      return;
+    }
+  parser_data->key = key;
+  parser_data->modifiers = (guint)modifiers;
+}
+
+static const GMarkupParser accelerator_parser =
+  {
+    accelerator_start_element
+  };
+
+static gboolean
+gtk_action_group_buildable_custom_tag_start (GtkBuildable     *buildable,
+                                            GtkBuilder       *builder,
+                                            GObject          *child,
+                                            const gchar      *tagname,
+                                            GMarkupParser    *parser,
+                                            gpointer         *user_data)
+{
+  AcceleratorParserData *parser_data;
+
+  if (child && strcmp (tagname, "accelerator") == 0)
+    {
+      parser_data = g_slice_new0 (AcceleratorParserData);
+      parser_data->child = child;
+      *user_data = parser_data;
+      *parser = accelerator_parser;
+
+      return TRUE;
+    }
+  return FALSE;
+}
+
+static void
+gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
+                                          GtkBuilder   *builder,
+                                          GObject      *child,
+                                          const gchar  *tagname,
+                                          gpointer     *user_data)
+{
+  AcceleratorParserData *data;
+  
+  if (strcmp (tagname, "accelerator") == 0)
+    {
+      GtkActionGroup *action_group;
+      GtkAction *action;
+      gchar *accel_path;
+      
+      data = (AcceleratorParserData*)user_data;
+      action_group = GTK_ACTION_GROUP (buildable);
+      action = GTK_ACTION (child);
+       
+      accel_path = g_strconcat ("<Actions>/",
+                               action_group->private_data->name, "/",
+                               gtk_action_get_name (action), NULL);
+
+      if (gtk_accel_map_lookup_entry (accel_path, NULL))
+       gtk_accel_map_change_entry (accel_path, data->key, data->modifiers, TRUE);
+      else
+       gtk_accel_map_add_entry (accel_path, data->key, data->modifiers);
+
+      gtk_action_set_accel_path (action, accel_path);
+      
+      g_free (accel_path);
+      g_slice_free (AcceleratorParserData, data);
+    }
+}
+
 /**
  * gtk_action_group_new:
  * @name: the name of the action group.
index 3e0ac69be6b1342bcf3043531e97931d1d79fa66..687567d3d5f17c990d4f2ec5110dbdb804b6ffac 100644 (file)
@@ -453,6 +453,29 @@ gtk_ui_manager_buildable_add_child (GtkBuildable  *buildable,
                                      pos);
 }
 
+static void
+child_hierarchy_changed_cb (GtkWidget *widget,
+                           GtkWidget *unused,
+                           GtkUIManager *uimgr)
+{
+  GtkWidget *toplevel;
+  GtkAccelGroup *group;
+  GSList *groups;
+
+  toplevel = gtk_widget_get_toplevel (widget);
+  if (!toplevel || !GTK_IS_WINDOW (toplevel))
+    return;
+  
+  group = gtk_ui_manager_get_accel_group (uimgr);
+  groups = gtk_accel_groups_from_object (toplevel);
+  if (g_slist_find (groups, group) == NULL)
+    gtk_window_add_accel_group (GTK_WINDOW (toplevel), group);
+
+  g_signal_handlers_disconnect_by_func (widget,
+                                       child_hierarchy_changed_cb,
+                                       uimgr);
+}
+
 static GObject *
 gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
                                          GtkBuilder   *builder,
@@ -464,10 +487,16 @@ gtk_ui_manager_buildable_construct_child (GtkBuildable *buildable,
   name = g_strdup_printf ("ui/%s", id);
   widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (buildable), name);
   if (!widget)
-    g_error ("Unknown ui manager child: %s\n", name);
-
+    {
+      g_error ("Unknown ui manager child: %s\n", name);
+      g_free (name);
+      return NULL;
+    }
   g_free (name);
 
+  g_signal_connect (widget, "hierarchy-changed",
+                   G_CALLBACK (child_hierarchy_changed_cb),
+                   GTK_UI_MANAGER (buildable));
   return G_OBJECT (widget);
 }
 
index a6577d73fc1d7dd996d9f457d95e36102738ef4a..f495f8833801cda0280f73804abfb289aacdd468 100644 (file)
@@ -259,6 +259,7 @@ gboolean test_uimanager_simple (void)
     "          <object class=\"GtkAction\" id=\"file\">"
     "            <property name=\"label\">_File</property>"
     "          </object>"
+    "          <accelerator key=\"n\" modifiers=\"GDK_CONTROL_MASK\"/>"
     "        </child>"
     "      </object>"
     "    </child>"